package com.luomu.base.biz.cookBook.thread.completableFuture;

import com.luomu.base.biz.cookBook.address.impl.ExpressAddressServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

@Service
public class CompletableFutureExample {
    private final Logger log = LoggerFactory.getLogger(ExpressAddressServiceImpl.class);


    @Autowired
    @Qualifier("asyncTaskExecutor")
    private Executor asyncTaskExecutor;

    public static void main(String[] args) {
        CompletableFutureExample c = new CompletableFutureExample();
        c.combineAsyncResults();


    }

    /**
     * 创建无返回值的异步任务
     */
    public void runAsync(){
        //异步运行一个任务使用CompletableFuture.runAsync方法 没有返回值
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Hello CompletableFuture!");
        },asyncTaskExecutor);
    }

    /**
     * 创建有返回值的异步任务
     */
    private void supplyAsync() {
        //2.获取结果
        CompletableFuture<String> futureWithStringResult = CompletableFuture.supplyAsync(() -> {
            // 异步运行一个任务并返回结果使用CompletableFuture.supplyAsync方法
            return "Hello CompletableFuture!";
        });
        try {
            System.out.println("result from futureWithStringResult: " + futureWithStringResult.get());
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 多个异步线程执行结果合并
     */
    private void combineAsyncResults() {

        // 多个异步执行结果合并到该集合
        List<Integer> resultList = new ArrayList<>();

        // 创建多个异步执行
        List<Integer> integers = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        List<CompletableFuture<Integer>> expressBatchFutureList = new ArrayList<>();
        for (Integer a : integers){
            CompletableFuture<Integer>  expressBatchFuture = CompletableFuture.supplyAsync(() -> {
                long threadId = Thread.currentThread().getId();
                long startTime = System.currentTimeMillis();
                log.info("【checkExpressInfo】-----threadId: " + threadId+"-------开始时间："+startTime+" ms");
                System.out.println(a);
                log.info("【checkExpressInfo】-----threadId: " + threadId+"-------结束时间："+System.currentTimeMillis()+" ms");
                log.info("【checkExpressInfo】--【耗时】---threadId: " + threadId+"-------结束时间："+(System.currentTimeMillis()-startTime)+"ms"+"-------------------");
                return a;
            });
            expressBatchFutureList.add(expressBatchFuture);
        }

        // 通过allOf对多个异步执行结果进行处理
        CompletableFuture<List<Integer>> combinedFuture = CompletableFuture.allOf(
                expressBatchFutureList.toArray(new CompletableFuture[expressBatchFutureList.size()])
        ).thenApply(v->
                expressBatchFutureList.stream().map(a-> {
                    try {
                        return a.get();
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                    return null;
                }).collect(Collectors.toList()));

        // 阻塞等待所有CompletableFuture执行完成
        // resultList中返回值的顺序就是插入多线程中任务的顺序
        try {
            resultList = combinedFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        System.out.println(resultList);
    }


}
